/*
	Copyright (c) 2012 by karmaleaving@qq.com. All rights RESERVED.
*/
/*
	This file defines class raw_buffer and class buffer.
	The "buffer" is like const-size-array that you may use "SSTD::buffer<Type> value(size)"
		rather than "Type value[SIZE]".
	The "raw_buffer" doesn't initialize the array.

	This is not in standard lib, while it is used in "algorithm.hpp" in this lib.
*/
#ifndef __BUFFER_H_VERSION_SSTD__
#define __BUFFER_H_VERSION_SSTD__
#include "memory.hpp"
SSTL_BEGIN
template<typename Type, typename Allocate = SSTD::allocator<Type>>
class raw_buffer
{
public:
	SSTD_NEST_TYPE_DEFINE(Type);
	STD_ITERATOR_DEFINE(pointer);
	typedef typename Allocate::rebind<Type>::other allocator_type;
protected:
	value_type* _buf;
	size_type _size;
	typedef allocator_type _allocator;
private:
	raw_buffer();
	raw_buffer(raw_buffer const&);
	void operator = (raw_buffer const&);
public:
	raw_buffer(size_t size)
		: _size(size)
	{
		_buf = _allocator::allocate(_size);
	}
	size_type size() const
	{
		return _size;
	}
	value_type& operator [](size_type pos)
	{
		ASSERT(pos < _size);
		return _buf[pos];
	}
	const value_type& operator [](size_type pos) const
	{
		ASSERT(pos < _size);
		return _buf[pos];
	}
	iterator begin()
	{
		return iterator(_buf);
	}
	iterator end()
	{
		return iterator(_buf + _size);
	}
	const_iterator begin() const
	{
		return iterator(_buf);
	}
	const_iterator end() const
	{
		return iterator(_buf + _size);
	}
	reverse_iterator rbegin()
	{
		return reverse_iterator(_buf + _size - 1);
	}
	reverse_iterator rend()
	{
		return reverse_iterator(_buf - 1);
	}
	const_reverse_iterator rbegin() const
	{
		return reverse_iterator(_buf + _size - 1);
	}
	const_reverse_iterator rend() const
	{
		return reverse_iterator(_buf - 1);
	}
	~raw_buffer()
	{
		_allocator::deallocate(_buf, _size);
	}
};
template<typename Type, typename Allocate = SSTD::allocator<Type>>
class buffer : public raw_buffer<Type, Allocate>
{
private:
	typedef raw_buffer _;
public:
	buffer(size_t size)
		: _(size)
	{
		SSTD::_memory_helper_<value_type>::initialize(_::begin(), _::end());
	}
	~buffer()
	{
		SSTD::_memory_helper_<value_type>::destroy(_::begin(), _::end());
	}
};
SSTL_END
#endif // __BUFFER_H_VERSION_SSTD__
